<template>
   <div>
       <div id="container" ref="container"></div>
   </div>
</template>

<script lang='ts'>
    import { computed, getCurrentInstance, ref, watch,onMounted,defineComponent, toRaw } from 'vue';
    import { templateRef } from '@vueuse/core';
    import * as TB from '../../../public/threebsp.js'
    import axios from 'axios'
    let $THREE = window.THREE;
    console.log(TB);
    let ThreeBSP = TB.default;
    interface createWallFun {
        (width:number,height:number,depth:number,angle?:any,material?:any, x?:number,y?:number,z?:number,name?:string):void
    };
    interface createResultBspFun {
        (bsp:any,objects_cube:any):void
    }
    interface createDoor{
        (direction:string,width:number,height:number,depth:number,angle?:any,x?:number,y?:number,z?:number,name?:string):void
    }
    export default defineComponent({
        props:{},
        setup(props,context){
            let {ctx}:any = getCurrentInstance();
            const container = templateRef<any>('container');
            const camera = ref<any>(null);
            const renderer = ref<any>(null);
            const mesh = ref<any>(null);
            const scene = ref<any>(new $THREE.Scene());
            const directionalLight = ref<any>();
            const pointLight = ref<any>(); 
            const ambientLight = ref<any>();
            const controls = ref<any>();
            const matArrayA = ref<any>([]);
            const matArrayB = ref<any>([]);

            const init = ()=>{
                initCamera();
                initLight();
                initRenderer();
                initControls();
                initContent();
                loop();
            }

            const initCamera =()=>{
                let _h = window.innerHeight;
                let _w = window.innerWidth;
                camera.value = new $THREE.PerspectiveCamera(45,_w/_h, 0.1, 10000);
                camera.value.position.set(0, 800, 1500);
                camera.value.lookAt(new $THREE.Vector3(0, 0, 0));
            }

            const initLight =()=>{
                let directionalLight = new $THREE.DirectionalLight( 0xffffff, 0.3 );//模拟远处类似太阳的光源
                directionalLight.color.setHSL( 0.1, 1, 0.95 );
                directionalLight.position.set( 0, 200, 0).normalize();
                scene.value.add(directionalLight);
                let ambient = new $THREE.AmbientLight( 0xffffff, 1 ); //AmbientLight,影响整个场景的光源
                ambient.position.set(0,0,0);
                scene.value.add(ambient);
            }

            const initRenderer =()=>{
                let _h = window.innerHeight;
                let _w = window.innerWidth;
                renderer.value = new $THREE.WebGLRenderer({antialias:true});
                renderer.value.setSize(_w,_h);
                renderer.value.setClearColor(0x4682B4,1.0);
                document.body.appendChild(renderer.value.domElement);
            }

                //创建地板
            const createFloor =()=>{
                let loader = new $THREE.TextureLoader();
                loader.load("/crate.gif",function(texture:any){
                    texture.wrapS = texture.wrapT = $THREE.RepeatWrapping;
                    texture.repeat.set( 10, 10 );
                    let floorGeometry = new $THREE.BoxGeometry(2600, 1400, 1);
                    let floorMaterial = new $THREE.MeshBasicMaterial( { map: texture, side: $THREE.DoubleSide } );
                    let floor = new $THREE.Mesh(floorGeometry, floorMaterial);
                    floor.position.y = -0.5;
                    floor.rotation.x = Math.PI / 2;
                    floor.name = "地面";
                    scene.value.add(floor);
                });
            }

                //墙上挖门，通过两个几何体生成BSP对象
                const createResultBsp:createResultBspFun  =(bsp:any,objects_cube:any)=>{
                    let material = new $THREE.MeshPhongMaterial({color:0x9cb2d1,specular:0x9cb2d1,shininess:30,transparent:true,opacity:1});
                    // let BSP = ThreeBSP.fromGeometry(bsp);
                    // // console.log("BSP",BSP);
                    // for(let i = 0; i < objects_cube.length; i++){
                    //     let less_bsp = ThreeBSP.fromGeometry(objects_cube[i]);
                    //     BSP = BSP.subtract(less_bsp);
                    // }
                    // console.log(BSP);
                    // let result = ThreeBSP.toMesh(material);
                    // result.material.flatshading = $THREE.FlatShading;
                    // result.geometry.computeFaceNormals();  //重新计算几何体侧面法向量
                    // result.geometry.computeVertexNormals();
                    // result.material.needsUpdate = true;  //更新纹理
                    // result.geometry.buffersNeedUpdate = true;
                    // result.geometry.uvsNeedUpdate = true;
                    // scene.value.add(result);
                }

                const createDoorBoth:createDoor=(direction,width, height, depth, angle, x, y, z, name,)=>{
                    let loader = new $THREE.TextureLoader();
                    loader.load("/bump.jpg",function(texture:any){
                        let doorgeometry = new $THREE.BoxGeometry(width, height, depth);
                        if(direction=="left"){
                            doorgeometry.translate(50, 0, 0);
                        }else{
                            doorgeometry.translate(-50, 0, 0);
                        }
                        let doormaterial = new $THREE.MeshBasicMaterial({map:texture,color:0xffffff});
                        doormaterial.opacity = 1.0;
                        doormaterial.transparent = true;
                        let door = new $THREE.Mesh( doorgeometry,doormaterial);
                        door.position.set(x, y, z);
                        door.rotation.y += angle*Math.PI;
                        scene.value.add(door);
                    })
                }

                const initContent =()=>{
                    createFloor();
                    createWallMaterail();
                    createCubeWall(10, 200, 1400, 0, new $THREE.MeshPhongMaterial({color: 0xafc0ca}), -1295, 100, 0, "墙面");
                    createCubeWall(10, 200, 1400, 1, new $THREE.MeshPhongMaterial({color: 0xafc0ca}), 1295, 100, 0, "墙面");
                    createCubeWall(10, 200, 2600, 1.5, new $THREE.MeshPhongMaterial({color: 0xafc0ca}), 0, 100, -700, "墙面");

                    //创建挖了门的墙
                    let wall = returnWallObject(2600, 200, 10, 0, matArrayB, 0, 100, 700, "墙面");
                    let door_cube1 = returnWallObject(200, 180, 10, 0, matArrayB, -600, 90, 700, "前门1");
                    let door_cube2 = returnWallObject(200, 180, 10, 0, matArrayB, 600, 90, 700, "前门2");
                    let window_cube1 = returnWallObject(100, 100, 10, 0, matArrayB, -900, 90, 700, "窗户1");
                    let window_cube2 = returnWallObject(100, 100, 10, 0, matArrayB, 900, 90, 700, "窗户2");
                    let window_cube3 = returnWallObject(100, 100, 10, 0, matArrayB, -200, 90, 700, "窗户3");
                    let window_cube4 = returnWallObject(100, 100, 10, 0, matArrayB, 200, 90, 700, "窗户4");
                    let objects_cube = [];
                    objects_cube.push(door_cube1);
                    objects_cube.push(door_cube2);
                    objects_cube.push(window_cube1);
                    objects_cube.push(window_cube2);
                    objects_cube.push(window_cube3);
                    objects_cube.push(window_cube4);
                    console.log(wall);
                    createResultBsp(wall, objects_cube);

                    createDoorBoth("left",100, 180, 2, 0, -700, 90, 700, "左门1");
                    createDoorBoth("right",100, 180, 2, 0, -500, 90, 700, "右门1");
                    createDoorBoth("left",100, 180, 2, 0, 500, 90, 700, "左门2");
                    createDoorBoth("right",100, 180, 2, 0, 700, 90, 700, "右门2");

                }

                const initControls =()=>{
                    controls.value = new $THREE.OrbitControls(camera.value, renderer.value.domElement);
                    controls.value.enableDamping = true;
                    controls.value.dampingFactor = 0.5;
                    // 视角最小距离
                    controls.value.minDistance = 100;
                    // 视角最远距离
                    controls.value.maxDistance = 5000;
                    // 最大角度
                    controls.value.maxPolarAngle = Math.PI/2.2;
                }

                const createCubeWall:createWallFun = (width,height,depth,angle,material,x,y,z,name)=>{
                    let cubeGeometry = new $THREE.BoxGeometry(width, height, depth );
                    let cube = new $THREE.Mesh(cubeGeometry,material );
                    cube.position.x = x;
                    cube.position.y = y;
                    cube.position.z = z;
                    cube.rotation.y += angle*Math.PI;  //-逆时针旋转,+顺时针
                    cube.name = name;
                    scene.value.add(cube);
                }

                //返回墙对象
                const returnWallObject:createWallFun =(width, height, depth, angle, material, x, y, z, name)=>{
                    let cubeGeometry = new $THREE.BufferGeometry(width, height, depth);
                    let cube = new $THREE.Mesh(cubeGeometry, material);
                    cube.position.x = x;
                    cube.position.y = y;
                    cube.position.z = z;
                    cube.rotation.y += angle*Math.PI;
                    cube.name = name;
                    return cube;
                }

                //创建墙纹理
                const createWallMaterail =()=>{
                    matArrayA.value.push(new $THREE.MeshPhongMaterial({color: 0xafc0ca}));  //前  0xafc0ca :灰色
                    matArrayA.value.push(new $THREE.MeshPhongMaterial({color: 0xafc0ca}));  //后
                    matArrayA.value.push(new $THREE.MeshPhongMaterial({color: 0xd6e4ec}));  //上  0xd6e4ec： 偏白色
                    matArrayA.value.push(new $THREE.MeshPhongMaterial({color: 0xd6e4ec}));  //下
                    matArrayA.value.push(new $THREE.MeshPhongMaterial({color: 0xafc0ca}));  //左    0xafc0ca :灰色
                    matArrayA.value.push(new $THREE.MeshPhongMaterial({color: 0xafc0ca}));  //右

                    matArrayB.value.push(new $THREE.MeshPhongMaterial({color: 0xafc0ca}));  //前  0xafc0ca :灰色
                    matArrayB.value.push(new $THREE.MeshPhongMaterial({color: 0x9cb2d1}));  //后  0x9cb2d1：淡紫
                    matArrayB.value.push(new $THREE.MeshPhongMaterial({color: 0xd6e4ec}));  //上  0xd6e4ec： 偏白色
                    matArrayB.value.push(new $THREE.MeshPhongMaterial({color: 0xd6e4ec}));  //下
                    matArrayB.value.push(new $THREE.MeshPhongMaterial({color: 0xafc0ca}));  //左   0xafc0ca :灰色
                    matArrayB.value.push(new $THREE.MeshPhongMaterial({color: 0xafc0ca}));  //右
                }

                const setReducesWallObject =()=>{
                    let wall = returnWallObject(2600, 200, 10, 0, matArrayB, 0, 100, 700, "墙面");
                    let door_cube1 = returnWallObject(200, 180, 10, 0, matArrayB, -600, 90, 700, "前门1");
                    let door_cube2 = returnWallObject(200, 180, 10, 0, matArrayB, 600, 90, 700, "前门2");
                    let window_cube1 = returnWallObject(100, 100, 10, 0, matArrayB, -900, 90, 700, "窗户1");
                    let window_cube2 = returnWallObject(100, 100, 10, 0, matArrayB, 900, 90, 700, "窗户2");
                    let window_cube3 = returnWallObject(100, 100, 10, 0, matArrayB, -200, 90, 700, "窗户3");
                    let window_cube4 = returnWallObject(100, 100, 10, 0, matArrayB, 200, 90, 700, "窗户4");
                }

                const loop =()=>{
                    requestAnimationFrame(loop);
                    renderer.value.render(toRaw(scene.value), camera.value);
                }

            onMounted(()=>{
                init();

            })
            return{
            }
        },
        components:{
        }
    })
</script>

<style scoped>
</style>
